package com.xianniu.ltc.aspect;

import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.Record;
import cn.devezhao.persist4j.engine.ID;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rebuild.core.Application;
import com.rebuild.core.UserContextHolder;
import com.rebuild.core.configuration.ConfigBean;
import com.rebuild.core.configuration.general.FormsBuilder;
import com.rebuild.core.configuration.general.FormsManager;
import com.rebuild.core.metadata.MetadataHelper;
import com.rebuild.core.privileges.UserService;
import com.xianniu.ltc.mapper.TRbhetong0Mapper;
import com.xianniu.ltc.model.entity.TProjectDetailDTO;
import com.xianniu.ltc.model.entity.TRbhetong0DTO;
import com.xianniu.ltc.model.po.ProjectAndDetailUpdatePO;
import com.xianniu.ltc.service.ProjectService;
import com.xxl.sso.core.entity.ReturnT;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author dingyuxin
 *  todo 后续优化成异步
 */
@Slf4j
@Aspect
@Component
public class RecordExtSaveAspect {
    @Value("${H5-URL}")
    private String h5Url;
    @Autowired
    private ProjectService projectService;
    @Autowired
    private TRbhetong0Mapper tRbhetong0Mapper;
    /**
     * 只有发送消息的时候触发
     * com.rebuild.core.service.notification
     */
    @Pointcut("execution(public * com.xianniu.ltc.api.ExternalController.*(..))")
    public void sendMessage(){}

    /**
     * 前置通知：在连接点之前执行的通知
     * @param joinPoint
     * @throws Throwable
     */
    @Around("sendMessage()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        List<String> saveMarkList = Arrays.asList("receivePmsWeiBao", "receivePmsJiHua", "receivePmsYingJi");
        String method = joinPoint.getSignature().getName();
        Optional<String> realKey = saveMarkList.stream().filter(b -> method.equalsIgnoreCase(b)).findAny();
        if(!realKey.isPresent()){
            log.info("{}不在拦截范围内", method);
            return joinPoint.proceed();
        }
        Object result = joinPoint.proceed();
        try{
            ReturnT ret = (ReturnT) result;
            Object recordId = ret.getData();
            String tenantCode = JSONObject.parseObject(JSONObject.toJSONString(joinPoint.getArgs()[0])).getString("tenantCode");
            String hetongbianhao = JSONObject.parseObject(JSONObject.toJSONString(joinPoint.getArgs()[0])).getString("hetongbianhao");
            handleEntity(recordId.toString(), tenantCode, hetongbianhao);
        }catch(Exception e){
            log.info("解析异常：{}", result);
            e.printStackTrace();
        }finally {
            return result;
        }
    }

    private void handleEntity(String recordId, String tenantCode, String hetongbianhao){
        // 实体编码
        Integer entityCode = Integer.parseInt(recordId.substring(0, 3));
        // 查询到的记录
        Record data = getRecordByAdmin(entityCode, recordId);
        if(Objects.isNull(data)){
            return;
        }
        doRecord(tenantCode, data, hetongbianhao);
        log.info("查询的记录：{}", data);
    }

    /**
     * admin查询record记录
     * @param entityCode
     * @param recordId
     * @return
     */
    private Record getRecordByAdmin(Integer entityCode, String recordId){
        // 商机类型条件：目前仅商机使用，查询指定layout布局
        String conditions = null;
        // 实体
        Entity mEntity = MetadataHelper.getEntity(entityCode);
        // 租户编码
        String tenantCode = UserContextHolder.getTenant();
        // 超级管理员ID
        ID user = UserService.ADMIN_USER;
        // 商机
        if (mEntity.getName().equalsIgnoreCase("rbshangji4")){
            // 如果是商机，根据ID查询商机类型的值
            Object[] object = Application.createQueryNoFilter(
                    "select shangjileixing from rbshangji4 where rbshangji4Id = ? and tenantCode = ?")
                    .setParameter(1, ID.valueOf(recordId))
                    .setParameter(2, tenantCode)
                    .unique();
            conditions = String.valueOf(object[0]);
        }
        // 实体配置
        ConfigBean model = FormsManager.instance.getFormLayout(mEntity.getName(), user, tenantCode, conditions);
        // 实体配置元素
        JSONArray elements = (JSONArray) model.getJSON("elements");
        // 查询到的记录
        Record data = FormsBuilder.instance.findRecord(ID.valueOf(recordId), user, elements, tenantCode);
        return data;
    }

    public void doRecord(String tenantCode, Record data, String hetongbianhao){
        ProjectNeedRecord type = ProjectNeedRecord.getByCode(data.getEntity().getEntityCode());
        if(Objects.isNull(type)){
            log.info("==当前要处理的实体编码是：{}[{}], 不需要记录到项目中", data.getEntity().getEntityCode(), data.getEntity().getDescription());
        }
        doSalesContract(data, tenantCode, hetongbianhao);
    }

    /**
     * 处理销售合同
     * @param data
     * @param tenantCode
     */
    private void doSalesContract(Record data, String tenantCode, String hetongbianhao){
        ID recordId = data.getPrimary();
        log.info("----------------> {}{}在租户{}下不存在，需要新增", data.getEntity().getDescription(), recordId.toString(), tenantCode);
        // 查询销售合同
        QueryWrapper<TRbhetong0DTO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("hetongbianhao", hetongbianhao);
        List<TRbhetong0DTO> saleContracts = tRbhetong0Mapper.selectList(queryWrapper);
        if(CollectionUtils.isEmpty(saleContracts)){
            log.info("销售合同{}不存在", hetongbianhao);
            return;
        }
        // 查询销售合同信息
        String saleContractId = saleContracts.get(0).getShangjibianhao();
        TProjectDetailDTO projectDetail = projectService.selectByEntityId(saleContractId, tenantCode);
        if (Objects.nonNull(projectDetail)) {
            addProjectDetail(data, tenantCode, recordId, projectDetail.getProjectId());
        }else {
            log.info("{}已经存在", data.getEntity().getDescription());
        }
    }

    /**
     * 新增项目明细
     * @param data
     * @param tenantCode
     * @param recordId
     * @param projectId
     */
    private void addProjectDetail(Record data, String tenantCode, ID recordId, String projectId) {
        String accessAddress = h5Url + data.getEntity().getName() + "&id=" + recordId.toString();
        ProjectAndDetailUpdatePO addPO = new ProjectAndDetailUpdatePO();
        addPO.setTenantCode(tenantCode);
        addPO.setAccessAddress(accessAddress);
        addPO.setEntityCode(data.getEntity().getName());
        addPO.setEntityId(recordId.toString());
        addPO.setNodeCode(data.getEntity().getName());
        addPO.setNodeName(data.getEntity().getDescription());
        projectService.addProjectDetail(addPO, projectId);
    }

    /**
     * 需要记录到项目中的类型
     */
    enum ProjectNeedRecord{
        rbshangji4(991, "商机", ""),
        shouqianfangan(920, "售前方案", "guanlianshangji"),
        rbhetong0(992, "项目合同（销售）", "shangjibianhao"),
        buchongxieyixiaoshou(908, "补充协议【销售】", "guanlianyuanhetong52"),
        jiaofushijianguanli(875, "交付事件管理", "guanlianxiangmuhetong"),
        rbfuwudan2(941, "服务单管理", "guanlianxiaoshouxiangmuhetong"),
        caigoushijianguanli(872, "采购事件管理", "guanlianxiangmuhetong"),
        yingjicaigoudingdan(883, "应急采购订单", "hetongbianhao"),
        jihuacaigouxiangmu(886, "维保拆包采购订单", "hetongbianhao"),
        jihuacaigoudingdanshangpin(882, "计划采购订单", "hetongbianhao");
        private Integer code;
        private String msg;
        private String resourceID;

        ProjectNeedRecord(Integer code, String msg, String resourceID){
            this.code = code;
            this.msg = msg;
            this.resourceID = resourceID;
        }

        /**
         * 根据code查询实例
         * @param entityCode
         * @return
         */
        public static ProjectNeedRecord getByCode(Integer entityCode){
            ProjectNeedRecord[] values = ProjectNeedRecord.values();
            for(ProjectNeedRecord value : values){
                if(value.code.equals(entityCode)){
                    return value;
                }
            }
            return null;
        }
    }
}